import * as cornerstone from "cornerstone-core";
import cornerstoneTools from "cornerstone-tools";
import _ from 'lodash';
import { useProcessData } from '@/store';
import { onMounted, ref, toRaw } from "vue";
import {
  createGoldPoint,
  updateGoldResultPoint,
  delGoldResult,
} from '@/api/processClient/processClient';
import type * as Type from '@/api/processClient/processClient.d';
import type * as PHStoreType from '@/store/modules/processHeader/type';
import { addViewList, resultForForm } from "@/utils/adapter";
import { useRoute } from "vue-router";

interface ImageResult {
  point1: {
    x: number,
    y: number
  },
  point2: {
    x: number,
    y: number
  }
}

const activeColor = "#008000";
const defaultColor = "#fbb03b";
const toolNameList = ["RectangleRoi"]; //"FreehandRoi", 

interface UseCornerstoneProps {
  element: string
}

export default function useCornerstone( props:UseCornerstoneProps ){
  const route = useRoute();
  const prData = useProcessData();
  const processClient = ref<any>(null);
  const element = ref<HTMLElement>();
  const currentToolName = ref<string>("");
  const prevTooName = ref<string>("");
  const imageWidth = ref(0);
  const imageHeight = ref(0);
  const isDown = ref(false);
  onMounted(()=>{
    element.value = document.querySelector(props.element) as HTMLElement;
    cornerstone.enable(element.value as HTMLElement);
    // element.value.addEventListener(cornerstoneTools.EVENTS.MEASUREMENT_ADDED, measurementAdded);
    element.value.addEventListener(cornerstoneTools.EVENTS.MEASUREMENT_MODIFIED, _.debounce(measurementModified, 50));
    element.value.addEventListener(cornerstoneTools.EVENTS.MEASUREMENT_COMPLETED, completed);
    element.value.addEventListener(cornerstoneTools.EVENTS.MOUSE_CLICK, singleClick);
    element.value.addEventListener(cornerstoneTools.EVENTS.MEASUREMENT_REMOVED, remove);
    element.value.addEventListener(cornerstoneTools.EVENTS.MOUSE_DOWN, mouseDown);
    element.value.addEventListener(cornerstoneTools.EVENTS.MOUSE_UP, mouseUp);
  })
  function mouseDown(){
    isDown.value = true;
  }
  function mouseUp(){
    isDown.value = false;
  }
  function remove(e:any){
    console.log("remove", e.detail);
    const { measurementData, toolName } = e.detail;
    if( isRectangle(toolName) ){
      handleRectangleData(measurementData)
    }
    if( isFreehand(toolName) ){
      handleFreehandData(measurementData);
    }
    addToolStateSingle(measurementData, toolName);
    completed(e);
  }
  function render(){
    cornerstoneTools.globalImageIdSpecificToolStateManager.clear(element.value);
    cornerstone.disable(element.value as HTMLElement);
    cornerstone.enable(element.value as HTMLElement);
    loadAndCacheImage(0, addToolState);
  }
  function nearBy( coords:any ){
    try {
      let [flag, data] = [false, null];
      const { state } = cornerstoneTools.store;
      state.tools.forEach( (tool:any)=> {
        const toolState = cornerstoneTools.getToolState(element.value, tool.name);
        if (toolState) {
          toolState.data.forEach((_data:any)=> {
            if( flag ) return;
            data = _data
            flag = tool.pointNearTool(element.value, _data, coords);
          });
        }
      });
      return [flag, data];
    } catch (error) {

    }
  }
  function singleClick(e:any){
    const [isNear, data] = nearBy(e.detail.currentPoints.canvas) as any;
    if( !isNear ) return;
    let flag = true;
    toolNameList.forEach((toolName:string) => {
      const items:any = cornerstoneTools.getToolState(element.value, toolName);
      const states = (items?.data || []).slice();
      states.forEach((item:any) => {
        if(item.uuid === data.uuid && flag ){
          flag = false;
          const currentItem = getImageResultInfoByUuid(item.uuid);
          if( Object.keys(currentItem).length === 0 ) return;
          setStateColor(currentItem.toolType, currentItem.uuid, activeColor, defaultColor);
          setLesionActiveClick(currentItem.lesionType, currentItem.uuid);
        }
      })
    })
  }
  function setLesionActiveClick(lesionType:number, uuid:string){
    const lesionResultList = prData.lesionResultList || [];
    const typeList = lesionResultList.filter(
      (item) => item.id === lesionType
    )[0];
    
    lesionResultList.map(item => item.isVisible = false);
    const viewList = typeList.viewList.filter(
      (item) => item.lesionData.uuid === uuid
    )[0];
    const imageGroupId = viewList.lesion.signForm.formId;
    const tempLesionList = typeList.lesionList.map(it => it.filter(t => t.imageGroupId === imageGroupId)).filter(item => item.length !== 0);
    
    typeList.isVisible = true;
    lesionResultList.map((it: { viewList: any[]; }) => it.viewList.map((t: { lesionData: { isCurrent: boolean; }; }) => t.lesionData.isCurrent = false));
    viewList.lesionData.isCurrent = true;
    processClient.value.getLesionSign(true, {currentItem: viewList});
    resultForForm(tempLesionList[0], viewList);
  }
  function setLesionActiveAdd(lesionType:number, uuid:string){
    const lesionResultList = prData.lesionResultList || [];
    const typeList = lesionResultList.filter(
      (item) => item.id === lesionType
    )[0];
    lesionResultList.map(item => item.isVisible = false);
    const currentList = typeList.viewList.filter(
      (item) => item.lesionData.uuid === uuid
    )[0];
    typeList.isVisible = true;
    lesionResultList.map((it: { viewList: any[]; }) => it.viewList.map((t: { lesionData: { isCurrent: boolean; }; }) => t.lesionData.isCurrent = false));
    currentList.lesionData.isCurrent = true;
    processClient.value.getLesionSign(true, {currentItem: currentList});
  }
  //通过uuid获取到病灶数据
  function getImageResultInfoByUuid(uuid:string): PHStoreType.LesionData{
    let lesionItem = {};
    const { lesionResultList } = prData;
    lesionResultList.forEach((item: any) => {
      if( Object.keys(lesionItem).length ) return;
      item.viewList.forEach((subItem:any)=> {
        if( subItem.lesionData.uuid === uuid ){
          lesionItem = subItem.lesionData;
        }
      });
    })
    return lesionItem as PHStoreType.LesionData;
  }

  function isFreehandDataError(data:any){
    const { handles } = data;
    const { points } = handles;
    return !Array.isArray(points) || ( Array.isArray(points) && points.length <= 1 );
  }
  function isRectangleDataError(data:any){
    const { handles } = data;
    const { end, start } = handles;
    const base = 5;
    return Math.abs(start.x - end.x) <= base && Math.abs(start.y - end.y) <= base;
  }
  
  async function setLoding(){
    new Promise((resolve)=> {
      setTimeout(()=>{
        prData.setLoading(false);
        resolve(true);
      }, 300)
    })
  }
  
  async function completed(e:any){
    let { measurementData, toolName } = e.detail;
    toolName = toolName === undefined ? "RectangleRoi" : toolName;
    e.detail.toolName = toolName;
    if( measurementData ){
      if( isFreehand(toolName) ){
        handleFreehandData(measurementData)
      }
      if( prData.loading ) return;
      prData.setLoading(true);
      const lesionItem: PHStoreType.LesionData = getImageResultInfoByUuid(measurementData.uuid);
      if( isFreehand(toolName) && isFreehandDataError(measurementData) ){
        await setLoding();
        return;
      }
      if( isRectangle(toolName) && isRectangleDataError(measurementData) ){
          await setLoding();
          return;
        }
      if( lesionItem && Object.keys(lesionItem).length ){
        //编辑
        measurementModified(e);
      } else {
        //新建
        measurementAdded(e);
      }
    }
  }
  //更新
  async function measurementModified(e:any){
    const { measurementData, toolName } = e.detail;
    if( measurementData && toolNameList.includes(toolName) ){  
      const lesionItem: PHStoreType.LesionData = getImageResultInfoByUuid(measurementData.uuid);
      if( Object.keys(lesionItem).length && lesionItem.approveLeisonId ){
        const imageResult = getRectangleImageResult(toolName, measurementData);
        updateToolState(lesionItem.toolType, lesionItem.uuid, imageResult as ImageResult);
        lesionItem.imageResult = imageResult;
        const model: Type.UpdateGoldResultPointParams = {
          imageId: lesionItem.approveLeisonId,
          imageResult: JSON.stringify(imageResult),
        }
        await updateGoldResultPoint(model);
      }
    }
    await setLoding();
  }
  //添加
  async function measurementAdded(e:any){
    const { toolName, measurementData } = e.detail;
    if( measurementData && toolNameList.includes(toolName) ){
      const imageResult = getRectangleImageResult(toolName, measurementData);
      if( !imageResult ) throw "error";
      const model: Type.CreateGoldPointParams = {
        imageGroupId: 0,
        imageAnnotationToolType: prData.currentLesion.imageAnnotationToolType,
        imageResult: JSON.stringify(imageResult),
        lesion: prData.currentLesion.lesion,
        seriesAnnotationResultId: prData.sarIdList[prData.index],
        auditStatus: 2
      };
      const res = await createGoldPoint(model);
      updateToolState(toolName, measurementData.uuid, imageResult as ImageResult);
      addNidusToList(res.data, measurementData.uuid);
    }
    await setLoding();
  }
  function addNidusToList( data:any, uuid:string){
    const { lesionResultList, dataList } = prData;
    const id = 4;
    const subItem = lesionResultList.find((subItem: any) => subItem.id === id);
    if( subItem ){
      const lesionItem: PHStoreType.LesionListItem = _.cloneDeep({
        ...prData.currentLesion,
        imageId: data.imageId,
        imageAnnotationToolType: data.imageAnnotationToolType,
        consistencyType: data.consistencyType,
        doctorId: data.doctorId,
        imageGroupId: data.imageGroupId,
        lesion: data.lesion,
        derivativeId: data.derivativeId,
        auditStatus: data.auditStatus,
        goldStandard: data.goldStandard,
        uuid,
        isCurrent: false,
        isEye: false,
        isApprove: true, 
        name: prData.lesionEnum[data.lesion],
      })
      subItem.lesionList.push([lesionItem])
      subItem.viewList = addViewList(subItem.lesionList, subItem.viewList, prData.lesionMap);
      dataList[0].children[3].lesionList = subItem.lesionList;
      dataList[0].children[3].viewList = subItem.viewList;
      setStateColor(lesionItem.imageAnnotationToolType, uuid, activeColor, defaultColor);
      setLesionActiveAdd(lesionItem.consistencyType, uuid);
    }
  }
  function getRectangleImageResult(toolName:string, measurementData:any): ImageResult | string {
    if( toolName !== 'RectangleRoi' ) return "";
    const { handles } = measurementData;
    const result: ImageResult = {
      point1: {
        x: handleX(handles.start.x),
        y: handleY(handles.start.y),
      },
      point2: {
        x: handleX(handles.end.x),
        y: handleY(handles.end.y),
      }
    }
    return result;
  }

  function handleX(x:number){
    if( x < 0  ) return 0;
    if( x > imageWidth.value ) return imageWidth.value;
    return x;
  }
  function handleY(y:number){
    if( y < 0  ) return 0;
    if( y > imageHeight.value ) return imageHeight.value;
    return y;
  }

  function handleRectangleData(data:any){
    const { handles }  = data;
    const { start, end } = handles;
    start.x = handleX(start.x);
    start.y = handleY(start.y);
    end.x = handleX(end.x);
    end.y = handleY(end.y);
  }

  function handleFreehandData(data:any){
    const { handles }  = data;
    const { points } = handles;
    points.forEach((item:any) => {
      item.x = handleX(item.x);
      item.y = handleY(item.y);
      if( Array.isArray(item.lines) && item.lines.length === 1  ){
        const lines  = [
          {
            x: item.lines[0].x,
            y: item.lines[0].y,
          }
        ]
        item.lines = lines;
      }
    })
  }

  //显示影像
  function loadAndCacheImage(index: number, callback = ()=> {} ){
    if( index < 0 || index >= prData.imageIds.length  ) return;
    const { imageId } = prData.imageIds[index||0];
    cornerstone.loadAndCacheImage(imageId).then((image) => {
      imageWidth.value = image.width;
      imageHeight.value = image.height;
      cornerstone.displayImage(element.value as HTMLElement, image);
      callback();
    });
  }
  function updateToolState(toolName:string, uuid:string, imageResult:ImageResult){
    const name = getToolName(toolName);
    const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState
    for(let ts in toolState){
      let data = toolState[ts][name]?.data || [];
      if( data.length === 0 ) continue;
      data.forEach((item:any)=> {
        if( item.uuid === uuid ){
          item.handles.start.x = imageResult.point1.x;
          item.handles.start.y = imageResult.point1.y;
          item.handles.end.x = imageResult.point2.x;
          item.handles.end.y = imageResult.point2.y;
        }
      })
    }
    updateImage();
  }
  //删除病灶
  function removeToolState(toolName:string, uuid:string, imageId: number){
    const name = getToolName(toolName);
    const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState
    for(let ts in toolState){
      let data = toolState[ts][name]?.data || [];
      if( data.length === 0 ) continue
      toolState[ts][name].data = data.filter((it:any) => uuid !== it.uuid)
    }
    _delGoldResult(imageId);
  }
  async function _delGoldResult(imageId:number){
    const model: Type.DelGoldResultParams = {
      imageId
    }
    const result = await delGoldResult(model);
    if(!result.data){
      prData.delLesionItem(imageId);
      updateImage();
    };
  }
  //显示或隐藏病灶
  function toggleToolVisible(toolName:string, uuid:string, isVisible: boolean){
    const name = getToolName(toolName);
    const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState;
    for(let ts in toolState){
      let data = toolState[ts][name]?.data || []
      data.forEach((item:any)=> {
        if( name && item.uuid === uuid ){
          item.visible = isVisible;
        }
      });
    }
    updateImage();
  }

  function setStateColor(toolName:string, uuid:string, currentActiveColor:string, defaultColor:string){
    const name = getToolName(toolName);
    const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState
    for(let ts in toolState){
      let data = toolState[ts][name]?.data || [];
      data.forEach((dataItem:any)=> {
        if(dataItem.uuid === uuid){
          dataItem.color = currentActiveColor;
        } else {
          dataItem.color = defaultColor;
        }
      });
    }
    updateImage();
  }
  function updateImage(){
    cornerstone.updateImage(element.value as HTMLElement);
  }

  //禁用
  function setToolDisabled(toolName:string){
    if( toolName ){
      cornerstoneTools.setToolDisabled(toolName, { mouseButtonMask: 1 });
    }
  }
  //设置当前工具
  function setToolActive(toolName:string){
    if( toolName ){
      currentToolName.value = toolName;
      cornerstoneTools.setToolActive(toolName, { mouseButtonMask: 1 })
    }
  }
  //设置平移工具
  function setPanActive(isPan:boolean){
    if( isPan ){
      prevTooName.value = currentToolName.value;
      currentToolName.value = "Pan";
      cornerstoneTools.setToolActive("Pan", { mouseButtonMask: 2 })
    } else {
      cornerstoneTools.setToolActive(currentToolName.value, { mouseButtonMask: 1 })
    }
  }
  //重置
  function reset(){
    cornerstone.reset(element.value as HTMLElement);
  }
  //清除尺子
  function clearLength(){
    cornerstoneTools.clearToolState(element.value as HTMLElement, "Length");
    cornerstoneTools.setToolPassive(currentToolName.value, { mouseButtonMask: 1 });
    updateImage();
  }
  //点击影像列表
  function handleClick(index:number){
    prData.imageIndex = index;
    loadAndCacheImage(index);
  }
  function setToolEnabled(toolName:string){
    cornerstoneTools.setToolEnabled(toolName, { mouseButtonMask: 1 });
  }

  //单个病灶数据添加到state里
  function addToolStateSingle( data: any, toolName:string ){
    let index = 0;  //图片索引
    const { imageId } = prData.imageIds[index];
    cornerstoneTools.globalImageIdSpecificToolStateManager.addImageIdToolState(imageId, toolName, data);
    cornerstone.updateImage(element.value as HTMLElement);
  }
  //初始化的时候执行一次
  function addToolState(){
    let index = 0;  //图片索引
    const { imageId } = prData.imageIds[index];
    const list = JSON.parse(JSON.stringify(toRaw(prData.lesionResultList)));
    list.forEach((item:any) => {
      item.viewList.forEach((subItem:any)=> {
        const { toolType, uuid, imageResult, color } = subItem.lesionData;
        const data = getRectangData(imageResult, uuid, color);
        const toolName = getToolName(toolType);
        setToolEnabled(toolName)
        cornerstoneTools.globalImageIdSpecificToolStateManager.addImageIdToolState(imageId, toolName, data);
      })
    })
    if( route.query.type === 'view' ){
      cornerstoneTools.setToolEnabled('RectangleRoi', { mouseButtonMask: 1 })
    } else {
      cornerstoneTools.setToolPassive('RectangleRoi', { mouseButtonMask: 1 })
    }
    cornerstone.updateImage(element.value as HTMLElement);
  }
  function getRectangData(imageResult:any, uuid:string, color:string){
    const data = {
      active:false,
      color: color,
      handles:{
        start: {
          ...imageResult.point1,
          active: false,
          highlight: true,
        },
        end: {
          ...imageResult.point2,
          active: false,
          highlight:true,
          moving:false,
        },
        initialRotation: 0,
        textBox: {
          active: false,
          allowedOutsideImage: true,
          drawnIndependently: true,
          hasBoundingBox: true,
          hasMoved:false,
          movesIndependently: false,
        }
      },
      invalidated: true,
      unit: "",
      uuid: uuid,
      visible: true,
    }
    return data;
  }
  function getToolName(toolType:string){
    const config:any = {
      RECTANGLE: "RectangleRoi",
    }
    return config[toolType];
  }
  function isRectangle(toolName:string){
    return ["RectangleRoi"].includes(toolName);
  }
  function isFreehand(toolName:string){
    return ["FreehandRoi"].includes(toolName);
  }
  function isGoodTool(toolName:string){
    return isRectangle(toolName) || isFreehand(toolName);
  }

  return {
    reset,
    render,
    clearLength,
    handleClick,
    setPanActive,
    setStateColor,
    setToolActive,
    removeToolState,
    toggleToolVisible,
    loadAndCacheImage,
    updateImage,
    processClient,
  }
  
}
